package com.antunnel.common.orm;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.antunnel.basicorm.core.BaseDao;
import com.antunnel.basicorm.core.OrmConverter;
import com.antunnel.basicorm.widget.pagination.Page;


/**
 * 基类Dao实现
 * 
 * @author n.wang
 * 
 */
@Repository
public class BaseDaoImpl implements BaseDao {

	@PersistenceContext
	private EntityManager entityManager;


	public EntityManager getEntityManager() {
		return entityManager;
	}

	/**
	 * 保存实体
	 * 
	 * @param obj
	 *            实体对象
	 */
	@Transactional 
	public void save(Object obj) {
		Assert.notNull(obj, "实体类不能为空");
		entityManager.persist(obj);
	}

	/**
	 * 修改实体
	 * 
	 * @param obj
	 *            实体对象
	 */
	public Object update(Object obj) {
		Assert.notNull(obj, "实体类不能为空");
		return entityManager.merge(obj);
	}

	/**
	 * 删除实体
	 * 
	 * @param obj
	 *            实体对象
	 */
	public void delete(Object obj) {
		Assert.notNull(obj);
		entityManager.remove(obj);
	}

	/**
	 * 根据ID删除实体类
	 * 
	 * @param clazz
	 *            实体类class
	 * @param id
	 *            主键
	 */
	public void delete(Class clazz, Serializable id) {
		Object entity = findById(clazz, id);
		delete(entity);
	}

	@SuppressWarnings("unchecked")
	public Object findById(Class clazz, Serializable id) {
		Object obj = entityManager.find(clazz, id);
		return obj;
	}

	public List findAll(Class clazz, String orderProperty, Boolean isAsc) {
		String queryString = " from " + clazz.getSimpleName();
		if (null != orderProperty && null != isAsc) {
			String orderType = isAsc == true ? " asc " : " desc ";
			queryString = queryString + " order by " + orderProperty + " "
					+ orderType;
		}
		return entityManager.createQuery(queryString).getResultList();
	}

	public List findByPage(Class clazz, Page page, Map<String, String> filterMap) {
		StringBuffer queryString = new StringBuffer(" from "
				+ clazz.getSimpleName() + " where 1=1 ");
		List valuelist = new ArrayList();
		OrmConverter.assemblyQuery(queryString, filterMap, valuelist);
		return findByHql(page, queryString, valuelist);
	}

	private List findByHql(Page page, StringBuffer hql, List valueList) {
		Object object[] = new Object[valueList.size()];
		for (int i = 0; i < valueList.size(); i++) {
			object[i] = valueList.get(i);
		}
		return findByHql(page, hql.toString(), object);
	}

	private List findByHql(final Page page, final String hql,
			final Object[] values) {
		int index = hql.toLowerCase().indexOf("from");
		String hqlCount = "select count(*) " + hql.substring(index);
		return findByHql(page, hqlCount, hql, values);
	}

	private List findByHql(final Page page, final String hqlCount,
			final String hql, final Object[] values) {
		Assert.notNull(page, "分页类对象page不能为空");
		Assert.notNull(hqlCount, "hqlCount不能为空");
		Assert.notNull(hql, "hql不能为空");
		Query query = entityManager.createQuery(hqlCount);
		Long totalCount = 0l;
		if (values != null && values.length > 0) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i + 1, values[i]);
			}
		}
		totalCount = ((Long) query.getSingleResult());
		page.setTotalCount(totalCount);
		int offset = 0;
		offset = page.getPageNum();
		query = entityManager.createQuery(hql);
		if (values != null && values.length > 0) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i + 1, values[i]);
			}
		}
		List list = query.setFirstResult(offset)
				.setMaxResults(page.getPageSize()).getResultList();
		page.setResults(list);
		return list;
	}
}
